import { urls } from "../assets/store.js";
import { DRACOLoader } from "../libs/three137/DRACOLoader.js";
import { GLTFLoader } from "../libs/three137/GLTFLoader.js";
import { AnimationMixer, Group, LoopOnce, Mesh, MeshBasicMaterial, Raycaster, SphereGeometry, Vector2, Quaternion, BufferGeometry, Vector3, Line } from "../libs/three137/three.module.js";
import { BulletHandler } from "./BulletHandler.js";
import { SFX } from "./SFX.js";

const { PI, ceil, max, min } = Math
class User {
    constructor(game, pos, heading) {
        this.initPos = pos;
        this.initHeading = heading;
        this.root = new Group();
        this.root.position.copy(pos);
        this.root.rotation.set(0, heading, 0, 'XYZ');

        this.game = game;
        this.camera = game.camera;
        this.raycaster = new Raycaster();

        game.scene.add(this.root);

        this.loadingBar = game.loadingBar;


        this.speed = 0;
        this.isFiring = false;

        this.load();
        this.initMouseHandler()
        this.initRefleDirection()
        this.temVec = new Vector3()
        this.temQuat = new Quaternion()
    }

    load() {
        const loader = new GLTFLoader();
        const dracoloader = new DRACOLoader();
        dracoloader.setDecoderPath('../libs/three137/draco/')

        loader.setDRACOLoader(dracoloader);
        loader.load(
            urls.eve2_glb,
            gltf => {
                this.root.add(gltf.scene);
                this.object = gltf.scene;
                const scale = 1.2;
                this.object.scale.set(scale, scale, scale);
                this.object.traverse((child) => {
                    if (child instanceof Mesh) {
                        child.castShadow = true;
                        if (child.name.includes('Rifle')) this.rifle = child

                    }
                })



                this.animations = {};
                gltf.animations.forEach((ani) => {
                    this.animations[ani.name.toLowerCase()] = ani
                })

                if (this.rifle) {
                    const geo = new BufferGeometry().setFromPoints([new Vector3(0, 0, 0), new Vector3(1, 0, 0)])
                    const line = new Line(geo);//  接收一个几何体，最终绘图方式应该是 Line strip
                    line.name = 'aim';
                    line.scale.x = 50;
                    line.position.set(0, 0, .5);// 矫正偏差，实际开发 可能需要一个gui 来调整 枪口是x轴方向， 
                    this.aim = line
                    this.rifle.add(line);
                    line.visible = false


                }
                this.mixer = new AnimationMixer(gltf.scene);
                this.action = 'idle';
                this.ready = true;
                this.game.startRendering()
                // if(this.game.npcHandler.ready && !this.game.bulletHandler)  this.game.bulletHandler = new BulletHandler(this.game) ;
            },
            xhr => {
                this.loadingBar.update('user', xhr.loaded, xhr.total)
            },
            err => {
                console.error(err)
            }
        )
    }

    initSounds() {
        this.sfx = new SFX(this.game.camera, '../assets/factory/sfx/', this.game.listener); // 共用一个listener 
        this.sfx.load('footsteps', true, .8, this.object)// 真的是路径错了？为什么不404呢  uniclound
        this.sfx.load('eve_groan', false, .8, this.object)
        this.sfx.load('shot', false, .8, this.object)
    }

    set action(name) {
        if (this.actionName === name.toLowerCase()) {
            return
        }
        // console.log(name);
        if (name === 'shot') {
            this.health -= 25;
            if (this.health >= 0) {// 血槽空了 人还活着，四条命好像确实是这个样子
                name = 'hit';
                this.game.active = false;
                setTimeout(() => {
                    this.game.active = true;
                }, 1000);
            }
            // console.log(name);
                // 开启死亡视觉
                this.game.tintScreen(name);
                this.game.ui.health = max(0, min(this.health / 100, 1))
                if (this.sfx) { this.sfx.play('eve_groan') }
        }

            if (this.sfx) {
                if (name === 'walk' || name === 'firingwalk' || name === 'run') {
                    this.sfx.play('footsteps')
                } else {
                    this.sfx.stop('footsteps')

                }
            }

        const clip = this.animations[name.toLowerCase()];

        if (clip) {
            const action = this.mixer.clipAction(clip);
            if (name === 'shot') {
                action.clampWhenFinished = true;//  停在最后一帧
                action.setLoop(LoopOnce)

                this.dead = true ;
                this.game.gameover()
            }
            // 没有给firing 设置循环，所以说，默认就是循环吗
            action.reset();
            const nofade = this.actionName === 'shot'
            this.actionName = name.toLowerCase();
            action.play();
            if (this.curAction) {
                if (nofade) {
                    this.curAction.enabled = false;
                } else {
                    this.curAction.crossFadeTo(action, .5);
                }
            }
            this.curAction = action;
            if (this.rifle && this.rifleDirection) {
                const q = this.rifleDirection[name.toLowerCase()];
                if (q) {
                    const start = new Quaternion();
                    start.copy(this.rifle.quaternion);
                    this.rifle.quaternion.copy(q)
                    this.rifle.rotateX(PI * .4); // 这个是让枪竖起来
                    const end = new Quaternion().copy(this.rifle.quaternion)

                    this.rotateRifle = { start, end, time: 0 }
                    this.rifle.quaternion.copy(start)
                }
            }
        }
    }

    set firing(mode) {
        if(this.dead) return 

        this.isFiring = mode;
        if (mode) {
            this.action = this.speed === 0 ? 'firing' : 'firingwalk';
            this.bulletTime = this.game.clock.getElapsedTime();// 一次开火的起始时刻
        } else {
            this.action = 'idle'
        }
    }

    shoot() {
        if (this.ammo < 1) return;

        if (!this.bulletHandler) {
            this.bulletHandler = this.game.bulletHandler;
        }
        this.aim.getWorldPosition(this.temVec)
        this.aim.getWorldQuaternion(this.temQuat)
        this.bulletHandler.createBullet(this.temVec, this.temQuat)
        this.bulletTime = this.game.clock.getElapsedTime();
        this.ammo--;
        this.game.ui.ammo = max(0, min(this.ammo / 100, 1));
        this.sfx.play('shot')

    }

    addSphere() {
        const geo = new SphereGeometry(.1, 8, 8);
        const mat = new MeshBasicMaterial({ color: 0xff0000 })
        const mesh = new Mesh(geo, mat);
        this.root.add(mesh);
    }
    get position() { return this.root.position }
    set position(v) { this.root.position.copy(v) }

    initMouseHandler() {
        this.game.renderer.domElement.addEventListener('pointerdown', raycast, false);

        const self = this;
        const mouse = new Vector2();

        function raycast(e) {
            mouse.set((e.clientX / window.innerWidth) * 2 - 1, 1 - 2 * (e.clientY / window.innerHeight))
            self.raycaster.setFromCamera(mouse, self.game.camera);
            const insects = self.raycaster.intersectObject(self.game.navMesh);
            // 按照这个逻辑 点到导航网络哪里 ，人物就会出现在哪里 ，传送啊
            if (insects.length) {
                const pt = insects[0].point;
                self.root.position.copy(pt); //  
                console.log(pt);
            }
        }

    }

    initRefleDirection() {

        this.rifleDirection = {};

        this.rifleDirection.idle = new Quaternion(-0.178, -0.694, 0.667, 0.203);
        this.rifleDirection.walk = new Quaternion(0.044, -0.772, 0.626, -0.102);
        this.rifleDirection.firingwalk = new Quaternion(-0.025, -0.816, 0.559, -0.147);
        this.rifleDirection.firing = new Quaternion(-0.054, -0.750, 0.633, -0.184);
        this.rifleDirection.run = new Quaternion(0.015, -0.793, 0.595, -0.131);
        this.rifleDirection.shot = new Quaternion(-0.082, -0.789, 0.594, -0.138);
    }

    reset() {
        this.ammo = 100;
        this.health = 100;
        this.dead =false ;
        this.action = 'idle';
        this.speed = 0;
        this.isFiring = false;
        this.root.rotation.set(0, this.initHeading, 0, 'XYZ')
        this.position = this.initPos;
    }
    update(dt) {
        this.mixer.update(dt)
        if (this.rotateRifle) {
            this.rotateRifle.time += dt;
            if (this.rotateRifle.time > .5) {
                this.rifle.quaternion.copy(this.rotateRifle.end);
                this.rotateRifle = null;
            } else {
                this.rifle.quaternion.slerpQuaternions(this.rotateRifle.start, this.rotateRifle.end, this.rotateRifle.time * 2)
            }
        }
        if (this.isFiring) {
            const elapsedTime = this.game.clock.getElapsedTime() - this.bulletTime;
            if (elapsedTime > .6) this.shoot() // 开枪。6s后子弹出膛
        }
    }

}

export { User }